﻿using System;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;
using Abp.Dependency;
using Abp.Extensions;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using RabbitMQ.Client;

namespace Abp.Rebus.Rabbit
{
    public class RabbitMqConnetionManager : IRabbitMqConnetionManager
    {
        public IConnection Connection { protected set; get; }

        public IModel Model { protected set; get; }

        private readonly IRabbitConfiguration _rabbitConfiguration;

        public RabbitMqConnetionManager(IRabbitConfiguration rabbitConfiguration)
        {
            _rabbitConfiguration = rabbitConfiguration;
            Init();
        }

        private void Init()
        {
            var conStr = this._rabbitConfiguration.RabbitMqConStr;
            if (string.IsNullOrEmpty(conStr))
            {
                throw new AbpException("请先配置消息队列的连接字符串!");
            }
            var uri = new Uri(conStr);
            var userName = string.Empty;
            var password = string.Empty;
            var virtualHost = "/";

            string userInfo = uri.UserInfo;
            if (!string.IsNullOrEmpty(userInfo))
            {
                string[] strArray = userInfo.Split(new char[] { ':' });
                if (strArray.Length > 2)
                {
                    throw new ArgumentException("Bad user info in AMQP URI: " + userInfo);
                }
                userName = strArray[0];
                if (strArray.Length == 2)
                {
                    password = strArray[1];
                }
            }

            var allSegments = uri.Segments;
            if (allSegments.Length == 2)
            {
                virtualHost = allSegments[1];
            }
            if (allSegments.Length > 2)
            {
                throw new ArgumentException("segment error" + string.Join(" ", allSegments));
            }


            var factory = new ConnectionFactory()
            {
                HostName = uri.Host,
                UserName = userName,
                Password = password,
                VirtualHost = virtualHost
            };
            Connection = factory.CreateConnection();
            Model = Connection.CreateModel();
        }


        public void Publish(Object message, string routingKey = "Abp.Rebus.Auditing.AuditMessage, Abp.Rebus")
        {
            if (message == null)
                return;

            var jObject = JObject.FromObject(message);
            jObject.First.AddBeforeSelf(new JProperty("$type", routingKey));
            var jsonStr = jObject.ToString();
            var body = Encoding.UTF8.GetBytes(jsonStr);
            var pro = Model.CreateBasicProperties();
            pro.Headers = new Dictionary<string, object>();
            var id = Guid.NewGuid().ToString();
            pro.Headers.Add("rbs2-msg-id", id);
            pro.Headers.Add("rbs2-content-type", "application/json;charset=utf-8");
            pro.Headers.Add("rbs2-senttime", DateTime.Now.ToString());
            pro.Headers.Add("rbs2-msg-type", routingKey);
            pro.Headers.Add("rbs2-corr-id", id);
            Model.BasicPublish(
                  exchange: "RebusTopics",
                             routingKey: routingKey,
                             basicProperties: pro,
                             body: body);
        }

        /// <summary>
        /// 发布消息到固定的队列
        /// </summary>
        /// <param name="message"></param>
        public void Direct(RebusMessageAdapter message)
        {
            if (string.IsNullOrEmpty(message.JsonMessage))
                return;
            var body = Encoding.UTF8.GetBytes(message.JsonMessage);
            var pro = Model.CreateBasicProperties();
            pro.Headers = new Dictionary<string, object>();
            pro.Headers.Add("rbs2-msg-id", Guid.NewGuid().ToString());
            pro.Headers.Add("rbs2-senttime", DateTime.Now.ToString());
            pro.Headers.Add("rbs2-msg-type",  message.MsgType);
            pro.Headers.Add("rbs2-corr-id", message.CorrId.ToString());
            pro.Headers.Add("rbs2-content-type", "application/json;charset=utf-8");
            Model.BasicPublish(
                  exchange: message.Exchange,
                             routingKey: message.RouteKey,
                             basicProperties: pro,
                             body: body);
        }

        public void Dispose()
        {
            if (Model != null)
            {
                Model.Dispose();
                Model = null;
            }

            if (Connection != null)
            {
                Connection.Dispose();
                Connection = null;
            }

        }

    }
}
